import random

from django.shortcuts import render
from django_redis import get_redis_connection
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework import status
from rest_framework_jwt.views import ObtainJSONWebToken

from carts.utils import merge_cart
from goods.models import SKU
from oauth.utils import generate_sign_openid, decode_sign_openid
from orders.serializers import UserOrderInfoSerializer
from .models import User
from rest_framework.permissions import IsAuthenticated

from rest_framework.generics import CreateAPIView, GenericAPIView, RetrieveAPIView, UpdateAPIView
from rest_framework import mixins
from rest_framework.viewsets import GenericViewSet
from . import serializers
from django.contrib.auth.hashers import make_password, check_password
from orders.models import OrderInfo

"""用户名查询"""
class CheckUsernameView(APIView):
    def get(self, request, username):
        # 根据用户名查询用户是否存在
        count = User.objects.filter(username=username).count()  # 返回0或者1
        # 返回响应
        data = {
            "count": count
        }
        return Response(data, status=status.HTTP_200_OK)

"""手机号判断是否存在"""
class CheckMobileView(APIView):
    def get(self, request, mobile):
        # 根据手机号查询是否存在
        count = User.objects.filter(mobile=mobile).count()  # 返回0或者1
        # 返回响应
        data = {
            "count": count
        }
        return Response(data, status=status.HTTP_200_OK)

"""注册功能接口"""
class RegisterUserView(CreateAPIView):  # 使用三级视图优化mixin加二级视图的业务
    serializer_class = serializers.RegisterUserSerializer  # 指定序列化器


# class RegisterUserView(mixins, GenericAPIView):
#     serializer_class = ""
#     def post(self, request):
#         # # 只使用二级视图
#         # # 获取参数 GenericAPIView
#         # dict_data = request.data
#         # # 创建序列化器效验
#         # serializer = self.get_serializer(data=dict_data)
#         # serializer.is_valid(raise_exception=True)
#         # # 数据入库
#         # serializer.save()
#         # # 返回响应
#         # return Response(serializer.data, status=status.HTTP_201_CREATED)
#
#         # 使用mixin类的create方法
#         return self.create(request)

"""用户中心视图"""
class UserInfoView(RetrieveAPIView):
    serializer_class = serializers.UserInfoSerializer
    permission_classes = [IsAuthenticated]  # 认证的用户

    def get_object(self):   # 重写get_object方法获得pk值
        return self.request.user

    # def get(self, request):
    #     # 获取数据
    #     # user = request.user    #  获取用户对象/ 如果用户没有登陆就获得匿名对象
    #     user= self.get_object()  # 获取对象
    #
    #     # 创建序列化器对象
    #     serializer = self.get_serializer(instance=user)
    #     # 返回数据
    #     return Response(serializer.data)

"""更新用户邮箱类视图"""
class EmailSendview(UpdateAPIView):
    serializer_class = serializers.EmailSendSerializer
    permission_classes = [IsAuthenticated]  # 认证登陆状态 授权普通用户访问

    def get_object(self):
        return self.request.user  # 重写get_object 返回一个用户

    # 单独使用二级视图创建视图
    # def put(self, request):
    #     # 获取数据
    #     dict_data = request.data
    #     user = self.get_object()  # 获得一个用户 更新到用户
    #     # 创建序列化器
    #     serializer = self.get_serializer(data=dict_data, instance=user)
    #     # 效验, 入库
    #     serializer.is_valid(reise_exception=True)
    #     serializer.save()
    #     # 返回
    #     return Response(serializer.data)  # 可以查看前端需要什么数据

    #     # 使用二级视图配合mixin类
    #     return self.update(requset)

"""激活邮箱视图"""
class EmailActiveview(APIView):
    def get(self, request):
        # 获取参数
        token = request.query_params.get("token")
        # 为空效验
        if not token:
            return Response(status=status.HTTP_400_BAD_REQUEST)

        # 解密token
        user = User.decode_token(token)  # 直接使用类方法
        if not user:
            return Response(status=status.HTTP_400_BAD_REQUEST)
        # 数据入库/修改有email_active属性
        user.email_active = True  # 如果user对象存在就将邮箱状态改为True
        user.save()
        #  返回响应
        return Response(status=status.HTTP_200_OK)

"""收货地址视图"""
class Addressview(mixins.CreateModelMixin,
                  mixins.UpdateModelMixin,
                  mixins.DestroyModelMixin,
                  GenericViewSet):
    serializer_class = serializers.AddressSerializer
    permission_classes = [IsAuthenticated]  # 效验权限 验证用户是否登陆

    def get_queryset(self):  # 获取用户地址信息
        return self.request.user.addresses.filter(is_deleted=False)

    def list(self, request):
        # 获取用户地址信息
        queryset = self.get_queryset()
        # 获取序列化器
        serializer = self.get_serializer(instance=queryset, many=True)

        return Response({
            "addresses": serializer.data,
            "limit": 20,
            "default_address_id": request.user.default_address_id
        })

    # 重写地址创建方法,判断是否达到上限二十个
    def create(self, request, *args, **kwargs):
        # 获取参数
        #     dict_data = request.data
        #     # 获取序列化器
        #     serializer = self.get_serializer(data=dict_data)
        #
        #     # 校验入库
        #     serializer.is_valid(raise_exception=True)
        #     serializer.save()
        #
        #     # 返回
        #     return Response(serializer.data)
        count = request.user.addresses.filter(is_deleted=False).count()  # 计算地址数量
        if count >= 21:
            return Response(status=status.HTTP_400_BAD_REQUEST)

        # 调用父类方法
        return super(Addressview, self).create(request, *args, **kwargs)

    # 更改用户默认地址
    @action(methods=['put'], detail=True)
    def status(self, request, pk):
        request.user.default_address_id = pk
        request.user.save()
        return Response(status=status.HTTP_200_OK)

    # 修改地址的标题
    @action(methods=["put"], detail=True)
    def title(self, request, pk):
        # 获取参数
        dict_data = request.data
        address = self.get_object()  # 获取当前的地址
        # 创建序列化器
        serializer = serializers.AddressTitleSerializer(instance=address, data=dict_data)

        # 效验数据,入库
        serializer.is_valid(raise_exception=True)
        serializer.save()
        # 返回
        return Response(serializer.data)

    # 重写destroy方法,实现逻辑删除
    def destroy(self, request, *args, **kwargs):
        instance = self.get_object()
        instance.is_deleted = True
        instance.save()
        return Response(status=status.HTTP_204_NO_CONTENT)


class TestView(APIView):
    def get(self, request, name, age):
        print(self.kwargs)  # 获取到的是路由地址中携带的资源参数
        return Response("%s, %s" % (name, age))

"""用户浏览商品记录视图"""
class UserBrowerHistoryView(CreateAPIView):
    serializer_class = serializers.UserBrowerHistorySerializer
    # 二级视图的方法实现
    # def post(self, request):
    #     # 获取参数
    #     dict_data = request.data
    #
    #     # 获取序列化器,效验
    #     serializer = self.get_serializer(data=dict_data)
    #     serializer.is_valid(raise_exception=True)
    #
    #     # 入库(保存到redis中)
    #     serializer.save()
    #     # 返回
    #     return Response(serializer.data)
    #

    def get(sel,request):
        # 获取redis中的数据
        redis_conn = get_redis_connection("history")
        sku_ids = redis_conn.lrange("history_%s" % request.user.id, 0, 4)
        # 拼接数据
        sku_list = []
        for sku_id in sku_ids:
            sku = SKU.objects.get(id=sku_id)
            sku_dict = {
                "default_image_url": sku.default_image_url,
                "name": sku.name,
                "price": sku.price,
                "comments": sku.comments,
                "id": sku.id
            }
            sku_list.append(sku_dict)

        return Response(sku_list)

"""重写登陆类视图"""
class UserObtainJSONWebToken(ObtainJSONWebToken):
    def post(self, request, *args, **kwargs):
        # 调用父类方法
        response = super().post(request, *args, **kwargs)
        # 获取序列化器
        serializer = self.get_serializer(data=request.data)  # 效验传输进来的账号密码

        # 判断是否效验成功
        if serializer.is_valid():
            # 获取user
            user = serializer.validated_data.get("user")

            # 合并购物车
            response = merge_cart(request, user, response)
            # 使用request获取cookie数据,使用user获得redis数据,使用response最后清除cookie数据
        return response

"""忘记密码类视图"""
class RetrievepasswordView(APIView):
    def get(self, request, username):
        try:
            user = User.objects.filter(mobile=username).first()  # 通过手机账号获取用户对象
            if not user :
                user = User.objects.filter(username=username).first()  # 通过用户名获取用户对象
        except Exception as e:
            Response(status=status.HTTP_400_BAD_REQUEST)

        dict_data = request.query_params

        text_code = dict_data['text']  # 获得图片验证码
        redis_conn = get_redis_connection('code')  # 获取redis对象
        redis_text = redis_conn.get("image_code_%s" % dict_data['image_code_id'])  # 获得redis存储的图片验证码

        if text_code.lower() != redis_text.decode().lower():
            # 判断图片验证码并且将大小写同步,将redis中取出的数据转成str
            return Response(status=status.HTTP_400_BAD_REQUEST)

        mobile = user.mobile
        access_token = generate_sign_openid(mobile)  # 加密access_token
        # 组织返回数据
        data = {
            'access_token': access_token,
            'mobile': mobile
        }
        return Response(data)

"""发送短信验证视图"""
class SmscodeView(APIView):
    def get(self, request):
        dict_data = request.query_params
        redis_conn = get_redis_connection('code')
        access_token = dict_data['access_token']
        mobile = decode_sign_openid(access_token)  # 解密token
        # 发送短信
        sms_code = "%06d" % random.randint(0, 99999)
        print("sms_code = %s" % sms_code)
        # 短信入库
        redis_conn.setex("sms_code_%s" % mobile, 300, sms_code)
        redis_conn.setex("send_flag_%s" % mobile, 60, True)
        return Response(status=status.HTTP_200_OK)

"""效验短信验证码"""
class GetsmscodeView(APIView):
    def get(self, request, username):
        dict_data = request.query_params  # 获取提交的表单数据
        try:
            user = User.objects.filter(mobile=username).first()  # 通过手机号判断是否用户账号,得到用户对象
            if not user:
                user = User.objects.filter(username=username).first()  # 通过用户判断是否用户账号, 得到用户对象
        except Exception as e:
            return Response(status=status.HTTP_400_BAD_REQUEST)

        mobile = user.mobile
        sms_code = dict_data['sms_code']
        redis_conn = get_redis_connection('code')
        redis_code = redis_conn.get('sms_code_%s' % mobile)
        if sms_code != redis_code.decode():
            return Response(status=status.HTTP_400_BAD_REQUEST)
        data ={
            'access_token': mobile,
            'user_id': user.id
        }
        return Response(data)
"""重置密码视图"""
class ResetPasswordView(GenericAPIView):
    def post(self, request, user_id):
        dict_data = request.data
        user = User.objects.get(id=user_id)
        password = dict_data['password']
        password2 = dict_data['password2']
        access_token = dict_data['access_token']

        # 判断
        if password != password2:
            return ValueError('两次输入的密码不一致')
        if user.mobile != access_token:
            return Response("用户异常")
        # 入库修改
        user.set_password(password)  # 将新密码加密
        user.save()  # 入库


        return Response(status=status.HTTP_200_OK)

    def put(self, request, user_id):
        dict_data = request.data  # 获取数据
        user = User.objects.get(id=user_id)
        old_password = dict_data['old_password']
        if not user.check_password(old_password):
            return Response(status=status.HTTP_400_BAD_REQUEST)
        if dict_data["password"] != dict_data["password2"]:
            return Response(status=status.HTTP_400_BAD_REQUEST)
        user.set_password(dict_data["password"])
        user.save()
        return Response(status=status.HTTP_200_OK)
"""订单列表显示"""
class ShowListordersView(GenericAPIView):
    serializer_class = UserOrderInfoSerializer
    # pagination_class = None
    def get(self, request):
        # 获取数据
        # dict_data = request.query_params
        user = self.request.user
        order = OrderInfo.objects.filter(user=user).order_by("-create_time")  # 使用创建时间来作为条件排序
        page = self.paginate_queryset(order)

        # 获取序列化器
        serializer =self.get_serializer(instance=page, many=True)
        respons = self.get_paginated_response(serializer.data)  # 使用django自由的分页模块

        return respons



